/**
 * 
 */
package co.fitstart.admin.service.impl;

import java.util.ArrayList;
import java.util.List;

import org.apache.commons.collections.CollectionUtils;
import org.springframework.stereotype.Service;

import co.fitstart.admin.dao.ArticleDao;
import co.fitstart.admin.entity.content.ArticleModuleSearch;
import co.fitstart.admin.entity.content.ArticleSearch;
import co.fitstart.admin.service.ArticleService;
import co.fitstart.entity.content.Article;
import co.fitstart.entity.content.ArticleModule;
import co.fitstart.entity.content.Module;

import com.demo2do.core.persistence.annotation.Dynamic;
import com.demo2do.core.support.Page;

/**
 * @author downpour
 *
 */
@Service("articleService")
public class ArticleServiceImpl extends DataServiceImpl<Article> implements ArticleService {
    
    @Dynamic
    private ArticleDao articleDao;

    /* (non-Javadoc)
     * @see co.fitstart.admin.service.content.ArticleService#list(java.lang.Long, com.demo2do.core.web.resolver.Page)
     */
    public List<ArticleModule> list(Long moduleId, Page page) {
        List<ArticleModule> result = articleDao.list(moduleId, page.getBeginIndex(), page.getMaxResultRecords());
        page.calculate(result.size());
        return result.size() > page.getEveryPage() ? result.subList(0, page.getEveryPage()) : result;
    }

    /* (non-Javadoc)
     * @see co.fitstart.admin.service.ArticleService#search(co.fitstart.admin.entity.content.ArticleModuleSearch, com.demo2do.core.support.Page)
     */
    @SuppressWarnings("unchecked")
    public List<ArticleModule> search(ArticleModuleSearch articleModuleSearch, Page page) {
        List<ArticleModule> result = genericDaoSupport.searchForList(articleModuleSearch.buildSentenceTemplate(), articleModuleSearch.buildParameters(), page.getBeginIndex(), page.getMaxResultRecords());
        page.calculate(result.size());
        return result.size() > page.getEveryPage() ? result.subList(0, page.getEveryPage()) : result;
    }

    /* (non-Javadoc)
     * @see co.fitstart.admin.service.ArticleService#search(co.fitstart.admin.entity.content.ArticleSearch, com.demo2do.core.support.Page)
     */
    @SuppressWarnings("unchecked")
    public List<Article> search(ArticleSearch articleSearch, Page page) {
        List<Article> result = genericDaoSupport.searchForList(articleSearch.buildSentenceTemplate(), articleSearch.buildParameters(), page.getBeginIndex(), page.getMaxResultRecords());
        page.calculate(result.size());
        return result.size() > page.getEveryPage() ? result.subList(0, page.getEveryPage()) : result;
    }
    
    /* (non-Javadoc)
     * @see co.fitstart.admin.service.content.ArticleService#disable(co.fitstart.common.entity.content.Article)
     */
    public void disable(final Article article) {
        
        genericDaoSupport.update(article.disable());
        
        // delete related article module
        articleDao.deleteArticleModules(article);
        
    }

    /* (non-Javadoc)
     * @see co.fitstart.admin.service.content.ArticleService#stick(co.fitstart.common.entity.content.Article, co.fitstart.common.entity.content.Module)
     */
    public void stick(Article article, Module module) {
        
        ArticleModule articleModule = this.getArticleModule(article, module);
        
        List<ArticleModule> sticks = articleDao.list(module);

        if(sticks.isEmpty()) { // no sticky ones
            
            genericDaoSupport.update(articleModule.stick(100));
            
        } else {
            
            // stick the activity using the 
            ArticleModule last = sticks.get(sticks.size() - 1);
            genericDaoSupport.update(articleModule.stick(last.getSerial()));
            
        }
        
        if(sticks.size() == module.getHotCount()) { // unstick the first one when the sticky queue is full
            
            ArticleModule first = sticks.get(0);
            genericDaoSupport.update(first.unstick());
            
        }
        
    }

    /* (non-Javadoc)
     * @see co.fitstart.admin.service.content.ArticleService#unstick(co.fitstart.common.entity.content.Article, co.fitstart.common.entity.content.Module)
     */
    public void unstick(Article article, Module module) {
        ArticleModule articleModule = this.getArticleModule(article, module);
        genericDaoSupport.update(articleModule.unstick());
    }
    
    /**
     * 
     * @param article
     * @param module
     * @return
     */
    private ArticleModule getArticleModule(Article article, Module module) {
        return articleDao.load(module, article);
    }
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.admin.service.content.ArticleService#createArticle(co.fitstart.common.entity.content.Article, java.util.List)
     */
    public void createArticle(Article article, List<Long> moduleIds) {
        
        // step1 save article
        genericDaoSupport.save(article.initialize());
        
        // step2 create article module
        if(CollectionUtils.isNotEmpty(moduleIds)) {
            
            for(Long moduleId : moduleIds) {
                
                Module module = genericDaoSupport.load(Module.class, moduleId);
                
                ArticleModule articleModule = new ArticleModule(article, module);
                genericDaoSupport.save(articleModule);
                
            }
            
        }
        
    }
    
    /*
     * @see co.fitstart.admin.service.content.ArticleService#editArticle(co.fitstart.common.entity.content.Article, java.util.List)
     */
    public void editArticle(Article article, List<Long> moduleIds) {
        
        // step1 update article
        genericDaoSupport.update(article);

        // step2 check module deletion
        List<Long> moduleIdsToDelete = new ArrayList<Long>();
        for(Long moduleId : article.getModuleIds()) {
            if(!moduleIds.contains(moduleId)) {
                moduleIdsToDelete.add(moduleId);
            }
        }
        
        // if exit article module to delete
        if(CollectionUtils.isNotEmpty(moduleIdsToDelete)) {
            articleDao.deleteArticleModules(article, moduleIdsToDelete);
        }
        
        // step3 check module creation
        for(Long moduleId : moduleIds) {
            
            if(!article.getModuleIds().contains(moduleId)) {
                
                Module module = genericDaoSupport.load(Module.class, moduleId);
                
                ArticleModule articleModule = new ArticleModule(article, module);
                genericDaoSupport.save(articleModule);
                
            }
        
        }
        
    }
}
